package com.framework.res;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

public class L2HContraintDate {

	private Date fecha1;
	private Date fecha2;
    private static final String initHHMMSS = " 00:00:00";
    private static final String endHHMMSS = " 23:59:59";
    
    
    private static final SimpleDateFormat SIMPLE_DATE_FORMAT =  new SimpleDateFormat("yyyy-MM-dd");
    
//    private enum TipoFecha{date, timestamp, sqldate};
//    private TipoFecha typedate;
    
	
	public L2HContraintDate(Date fecha_inicial, Date fecha_final) {
	    this.fecha1 =  initFechaInHHMMSS(fecha_inicial, TypeInit.Init00_00_00);
	    this.fecha2 =  initFechaInHHMMSS(fecha_final, TypeInit.end23_59_59);
//	    typedate = TipoFecha.date;
	}
	
	public L2HContraintDate(Timestamp fecha_inicial, Timestamp fecha_final) {
	    this.fecha1 =  initFechaInHHMMSS(fecha_inicial, TypeInit.Init00_00_00);
	    this.fecha2 =  initFechaInHHMMSS(fecha_final, TypeInit.end23_59_59);
//	    typedate = TipoFecha.timestamp;
	}
	
	public L2HContraintDate(java.sql.Date fecha_inicial, java.sql.Date fecha_final) {
	    this.fecha1 =  initFechaInHHMMSS(fecha_inicial, TypeInit.Init00_00_00);
	    this.fecha2 =  initFechaInHHMMSS(fecha_final, TypeInit.end23_59_59);
//	    typedate = TipoFecha.sqldate;
	}
	
	public static Timestamp getAsInitOfMonth(Date date){
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.DAY_OF_MONTH, 1);
		return initFechaInHHMMSS(calendar.getTime(), TypeInit.Init00_00_00);
	}
	
	
	public static Timestamp getAsEndOfMonth(Date date){
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.DAY_OF_MONTH, 1);
		calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH)); 
		return initFechaInHHMMSS(calendar.getTime(), TypeInit.end23_59_59);
	}
	
	public static long getDiferentDay(Date fecha1, Date fecha2){
		final long MILLSECS_PER_DAY = 24 * 60 * 60 * 1000; //Milisegundos al día
        return ((fecha1.getTime() - fecha2.getTime()) / MILLSECS_PER_DAY);
	}
	
	public static long getDiferentDay(Date fecha1, Date fecha2, Boolean solo_dias){
		final long MILLSECS_PER_DAY = 24 * 60 * 60 * 1000; //Milisegundos al día
		if(solo_dias){
			return ((fecha1.getTime()/ MILLSECS_PER_DAY) - (fecha2.getTime()/ MILLSECS_PER_DAY));	
		}else{
			return ((fecha1.getTime() - fecha2.getTime()) / MILLSECS_PER_DAY);
		}        
	}
	
	public enum TypeInit {Init00_00_00, end23_59_59};
	
	public static Timestamp initFechaInHHMMSS(Date date, TypeInit typeInit){
	   return Timestamp.valueOf(new SimpleDateFormat("yyyy-MM-dd").format(date)+(typeInit == TypeInit.Init00_00_00 ? initHHMMSS : endHHMMSS));	
	}
	
	public static String getL2hDateForQueryStringAsLong(Date date, TypeInit typeInit){
		return  "" + initFechaInHHMMSS(date, typeInit).getTime(); 
	}
	
	public String inQuery(String nameDBField){
		return "("+nameDBField+" BETWEEN "+getL2hDateForQueryStringAsLong(fecha1, TypeInit.Init00_00_00)+" AND "+getL2hDateForQueryStringAsLong(fecha2, TypeInit.end23_59_59)+")";
	}

	public boolean validate(Date fecha){
		if (fecha1 != null || fecha2 != null) {
			if (fecha.compareTo(fecha1) < 0 || fecha.compareTo(fecha2) > 0) {
				return false;
			}
			return true;
		}
		return false;
	}

	public void validate(Date fecha, String msjError) throws Exception {
		if(!validate(fecha)){throw new Exception(msjError);}
	}
	
	public static void validate(Date fecha_init, Date fecha_end, String msjError) throws Exception{
	    if (fecha_init.compareTo(fecha_end) > 0 ) {throw new Exception(msjError);}
	}
	
	public static void validateIncludeToDay(Date fecha_init, Date fecha_end, String msjError) throws Exception{
	    if(Calendar.getInstance().getTime().compareTo(fecha_init) > 0){throw new Exception("Esta fecha ya paso");}
	    else if (fecha_init.compareTo(fecha_end) > 0 ) {throw new Exception(msjError);}
	}
	
	public static void validarFecha(Date fecha_init, Date fecha_end, String msjError) throws Exception{
		if (fecha_init.compareTo(fecha_end) > 0 ) {throw new Exception(msjError);}
	}
	
	public static boolean nextDate(Date fecha_init, Date fecha_end){
	    return (fecha_init.compareTo(fecha_end) < 0);
	}
	
	public Date getFecha1AsInitOfMonth(){
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(fecha1);
		calendar.set(Calendar.DAY_OF_MONTH, 1);
		return calendar.getTime();
	}
	
	
	public Date getFecha2AsEndOfMonth(){
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(fecha2);
		calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH)); 
		return calendar.getTime();
	}
	
	public static int getDiferenciaEntreMeses(Date fecha_incio, Date fecha_final){
		int mesesIniciales = (getAnio(fecha_incio) * 12) + (getMes(fecha_incio) + (isfinMes(fecha_incio) ? 1 : 0));
		int mesesFinales = (getAnio(fecha_final) * 12) + (getMes(fecha_final) + (isfinMes(fecha_final) ? 1 : 0));
		return mesesFinales - mesesIniciales;
	}
	
	private static boolean isfinMes(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		return calendar.get(Calendar.DAY_OF_MONTH) == calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
	}
	
	public static int getMaximoDia(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
	}
	
	public static final int getDecremento(Date fecha_inicial){
		if(isInicioMes(fecha_inicial)){
			return 0;
		}else{
			return getDia(fecha_inicial) - 1;
		}
	}
	
    public static final int getIncremento(Date fecha_final){
    	if(isfinMes(fecha_final)){
			return 0;
		}else{
			return getDia(fecha_final);
		}
	}
    
    public static int getDia(Date date){
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		return calendar.get(Calendar.DAY_OF_MONTH);
	}
    
	
	private static boolean isInicioMes(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		return calendar.get(Calendar.DAY_OF_MONTH) == 1;
	}
	
	
	public static int getAnio(Date date){
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		return calendar.get(Calendar.YEAR);
	}
	
	public static int getMes(Date date){
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		return calendar.get(Calendar.MONTH);
	}
	
	public static boolean estaDentroRango(Date fecha_evaluacion, Date fecha_inicial, Date fecha_final) {
		return fecha_evaluacion.compareTo(fecha_inicial) >= 0 && fecha_evaluacion.compareTo(fecha_final) < 0;
	}
	
	
	public static boolean estaDentroRangoYYMMDD(Date fecha_evaluacion, Date fecha_inicial, Date fecha_final) {
		return java.sql.Date.valueOf(
				SIMPLE_DATE_FORMAT.format(fecha_evaluacion))
				.compareTo(
						java.sql.Date.valueOf(SIMPLE_DATE_FORMAT
								.format(fecha_inicial))) >= 0
				&& java.sql.Date.valueOf(
						SIMPLE_DATE_FORMAT.format(fecha_evaluacion)).compareTo(
						java.sql.Date.valueOf(SIMPLE_DATE_FORMAT
								.format(fecha_final))) <= 0; 
	}
	
	

	public Date getFecha1() {
		return fecha1;
	}

	public Date getFecha2() {
		return fecha2;
	}
	
}